﻿using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using System.Diagnostics;
using System.Collections.Generic;
using DVK.SP2007.Constants;

namespace DVK.SP2007
{
    /// <summary>
    /// The main goal of this receiver is add all of the Jobs required by the solution to the web application.
    /// 
    /// The receiver is attached to DVK.SP2007.Jobs feature.
    /// </summary>
    public class TimerJobsFeatureReceiver : SPFeatureReceiver
    {
        private const string PropertySendReceiveJobTime = "SendReceiveJobTime";
        private const string PropertySynchronizeOrganisationsTime = "SynchronizeOrganisationsTime";
        private const string PropertySendReceiveJobName = "SendReceiveJobName";
        private const string PropertySynchronizeOrganisationsJobName = "SynchronizeOrganisationsJobName";
        private const string PropertyDvkMessagesArchiveJobTime = "DvkMessagesArchiveJobTime";
        private const string PropertyDvkMessagesArchiveJobName = "DvkMessagesArchiveJobName";
        private const string PropertyLogSourceLevel = "LogSourceLevel";
        private JobsResourceManager _resourceManager;


        /// <summary>
        /// Occurs after a Feature is activated.
        /// 
        /// Adds all solution related jobs to the web application.
        /// </summary>
        /// <param name="properties">An <see cref="T:Microsoft.SharePoint.SPFeatureReceiverProperties"></see> object that represents the properties of the event.</param>
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            Logger logger = new Logger(LoggingSources.TimerJobsFeatureReceiver, SourceLevels.Information);

            //Get web
            SPSite site = null;
            SPWeb web = null;

            try
            {
                if (properties.Feature.Parent is SPSite)
                {
                    site = properties.Feature.Parent as SPSite;
                    web = site.RootWeb;
                }
                else if (properties.Feature.Parent is SPWeb)
                {
                    web = properties.Feature.Parent as SPWeb;
                }
                else
                {
                    logger.LogError(
                            LoggerEvents.FailedToCreateTimerJobs,
                            "{0}: Scope '{1}' not supported.", 
                            web.Url, 
                            properties.Feature.Definition.Scope.ToString()
                        );
                    return;
                }

                //Create required eventsource
                FeatureReceiverHelper.CreateEventLogSource(LoggingSources.TimerJobsFeatureReceiver);
                logger.LogInformative("{0}: Successfully created eventlog source for '{1}'.", web.Url, LoggingSources.TimerJobsFeatureReceiver);

                //Get resourcemanager for timer jobs
                _resourceManager = new JobsResourceManager();

                //Delete jobs just in case they were not removed properly before
                DeleteJobs(properties, web, logger);

                //Start creating timer jobs
                AddArchiveDvkMessagesJob(properties.Definition.Properties, web);
                logger.LogInformative("{0}: Successfully added ArchiveDvkMessagesJob.", web.Url);

                AddSendReceiveJob(properties.Definition.Properties, web);
                logger.LogInformative("{0}: Successfully added SendReceiveJob.", web.Url);

                AddSynchronizeOrganisationsJob(properties.Definition.Properties, web);
                logger.LogInformative("{0}: Successfully added SynchronizeOrganisationsJob.", web.Url);
            }
            finally
            {
                if (web != null)
                    web.Dispose();
                if (site != null)
                    site.Dispose();
            }
        }

        /// <summary>
        /// Adds the "Archive DVK messages job".
        /// </summary>
        /// <param name="properties">The properties.</param>
        /// <param name="web">The web.</param>
        private void AddArchiveDvkMessagesJob(SPFeaturePropertyCollection properties, SPWeb web)
        {
            SPSchedule archiveDvkMessagesSchedule =
                SPSchedule.FromString(properties[PropertyDvkMessagesArchiveJobTime].Value);
            DvkMessagesArchiveJob archiveDvkMessagesJob =
                new DvkMessagesArchiveJob(properties[PropertyDvkMessagesArchiveJobName].Value, web.Site.WebApplication);
            archiveDvkMessagesJob.Schedule = archiveDvkMessagesSchedule;
            archiveDvkMessagesJob.Title = _resourceManager.GetString("JobTitleMessageArchiving");
            archiveDvkMessagesJob.Properties.Add(Settings.DvkSiteUrl, web.Site.Url);
            archiveDvkMessagesJob.Properties.Add(Settings.JobsLogSourceLevel, properties[PropertyLogSourceLevel].Value);
            FeatureReceiverHelper.CreateEventLogSource(LoggingSources.DvkMessagesArchiveJob);
            archiveDvkMessagesJob.Update();
        }

        /// <summary>
        /// Adds the "Synchronize organisations job".
        /// </summary>
        /// <param name="properties">The properties.</param>
        /// <param name="web">The web.</param>
        private void AddSynchronizeOrganisationsJob(SPFeaturePropertyCollection properties, SPWeb web)
        {
            SPSchedule synchronizeOrganisationsSchedule =
                SPSchedule.FromString(properties[PropertySynchronizeOrganisationsTime].Value);
            SynchronizeOrganisationsJob synchronizeOrganisationsJob =
                new SynchronizeOrganisationsJob(properties[PropertySynchronizeOrganisationsJobName].Value, web.Site.WebApplication);
            synchronizeOrganisationsJob.Schedule = synchronizeOrganisationsSchedule;
            synchronizeOrganisationsJob.Title = _resourceManager.GetString("JobTitleSynchronizeOrganisations");
            synchronizeOrganisationsJob.Properties.Add(Settings.DvkSiteUrl, web.Site.Url);
            synchronizeOrganisationsJob.Properties.Add(Settings.JobsLogSourceLevel, properties[PropertyLogSourceLevel].Value);
            FeatureReceiverHelper.CreateEventLogSource(LoggingSources.SynchronizeOrganisationsJob);
            synchronizeOrganisationsJob.Update();
        }

        /// <summary>
        /// Adds the "Send/Receive job".
        /// </summary>
        /// <param name="properties">The properties.</param>
        /// <param name="web">The web.</param>
        private void AddSendReceiveJob(SPFeaturePropertyCollection properties, SPWeb web)
        {
            SPSchedule sendRecieveSchedule =
                SPSchedule.FromString(properties[PropertySendReceiveJobTime].Value);
            SendReceiveJob sendRecieveJob = new SendReceiveJob(properties[PropertySendReceiveJobName].Value, web.Site.WebApplication);
            sendRecieveJob.Schedule = sendRecieveSchedule;
            sendRecieveJob.Title = _resourceManager.GetString("JobTitleSendReceive");
            sendRecieveJob.Properties.Add(Settings.DvkSiteUrl, web.Site.Url);
            sendRecieveJob.Properties.Add(Settings.JobsLogSourceLevel, properties[PropertyLogSourceLevel].Value);
            FeatureReceiverHelper.CreateEventLogSource(LoggingSources.SendReceiveJob);
            sendRecieveJob.Update();
        }

        /// <summary>
        /// Occurs when a Feature is deactivated.
        /// 
        /// Removes all solution related jobs from web application.
        /// </summary>
        /// <param name="properties">An <see cref="T:Microsoft.SharePoint.SPFeatureReceiverProperties"></see> object that represents the properties of the event.</param>
        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            using (SPWeb web = (SPWeb)properties.Feature.Parent)
            {
                Logger logger = new Logger(LoggingSources.TimerJobsFeatureReceiver, SourceLevels.Information);
                DeleteJobs(properties, web, logger);
            }
        }

        /// <summary>
        /// Deletes the timer jobs.
        /// </summary>
        /// <param name="properties">The properties.</param>
        /// <param name="web">The web.</param>
        /// <param name="logger">The logger.</param>
        private static void DeleteJobs(SPFeatureReceiverProperties properties, SPWeb web, Logger logger)
        {
            List<string> jobNamesToDelete = new List<string>(3);
            jobNamesToDelete.Add(properties.Definition.Properties[PropertySendReceiveJobName].Value);
            jobNamesToDelete.Add(properties.Definition.Properties[PropertySynchronizeOrganisationsJobName].Value);
            jobNamesToDelete.Add(properties.Definition.Properties[PropertyDvkMessagesArchiveJobName].Value);
            foreach (SPJobDefinition job in web.Site.WebApplication.JobDefinitions)
            {
                if (jobNamesToDelete.Contains(job.Name))
                {
                    logger.LogInformative("{0}: Successfully deleted '{1}' timer job.", web.Url, job.Name);
                    job.Delete();
                }
            }
        }

        /// <summary>
        /// Occurs after a Feature is installed.
        /// </summary>
        /// <param name="properties">An <see cref="T:Microsoft.SharePoint.SPFeatureReceiverProperties"></see> object that represents the properties of the event.</param>
        public override void FeatureInstalled(SPFeatureReceiverProperties properties)
        {
        }

        /// <summary>
        /// Occurs when a Feature is uninstalled.
        /// </summary>
        /// <param name="properties">An <see cref="T:Microsoft.SharePoint.SPFeatureReceiverProperties"></see> object that represents the properties of the event.</param>
        public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
        {
        }
    }
}

